/* moniter.c - global functions according to moniter.h */

#include	"monitor.h"

u8int cx = 0, cy = 0;
u16int *vmem = (u16int *) 0xB8000;

static void move_cursor(){
	u16int cloc = cy * DEFCOL + cx;
	outb(0x3D4, 14);
	outb(0x3D5, cloc >> 8);
	outb(0x3D4, 15);
	outb(0x3D5, cloc);
}

static void scroll(){
	u8int attb = (BLACK << 4) | (WHITE & 0x0F);
	u16int blank = 0x20 | (attb << 8);

	if(cy > DEFROW){
		int i;
		for(i = 0 * DEFCOL; i < DEFROW * DEFCOL; i++){
			vmem[i] = vmem[i + DEFCOL];
		}

		for(i = DEFROW * DEFCOL; i < (DEFROW + 1) * DEFCOL; i++){
			vmem[i] = blank;
		}

		cy = DEFROW;
	}
}

void monitor_put(char c){
	u8int cback = DEFBACK, cfore = DEFFORE;

	u8int attb = (cback << 4) | (cfore & 0x0f);
	u16int att = attb << 8, *location;

	switch(c){
		case 0x08:	/* backspace */
			if(cx)	cx--;
			break;
		case 0x09:	/* tab */
			cx = (cx + DEFTAB) & ~(DEFTAB - 1);
			break;
		case '\r':	/* cr */
			cx = 0;
			break;
		case '\n':	/* lf */
			cx = 0;
			cy++;
			break;
		default:	/* any printable */
			if(c >= ' '){
				location = vmem + (cy * DEFCOL + cx);
				*location = att | c;
				cx++;
			}
	}

	if(cx >= DEFCOL){
		cx = 0;
		cy++;
	}

	scroll();
	move_cursor();
}

void monitor_clear(){
	u8int attb = (BLACK << 4) | (WHITE & 0x0F);
	u16int blank = 0x20 | (attb << 8);

	int i;
	for(i = 0; i < (DEFROW + 1) * DEFCOL; i++)
		vmem[i] = blank;
	cx = 0;
	cy = 0;
	move_cursor();
}

void monitor_write(char *c){
	int i = 0;
	while(c[i])
		monitor_put(c[i++]);
}

void monitor_write_hex(u32int n){
	s32int tmp;

	monitor_write("0x");

	char noZeroes = 1;

	int i;
	for(i = 28; i > 0; i -= 4){
		tmp = (n >> i) & 0xF;
		if(tmp == 0 && noZeroes != 0){
			continue;
 	       	}
	    
		if(tmp >= 0xA){
	            	noZeroes = 0;
  	          	monitor_put (tmp-0xA+'a' );
 	       	}
		else{
  	          	noZeroes = 0;
   	         	monitor_put( tmp+'0' );
		}
	}
  
 	tmp = n & 0xF;
	if(tmp >= 0xA){
        	monitor_put (tmp-0xA+'a');
    	}
    	else{
        	monitor_put (tmp+'0');
    	}
}

void monitor_write_dec(u32int n){

	s32int acc;
	char c[32], c2[32];
    	int i = 0, j = 0;

	acc = n;

	if (n == 0){
        	monitor_put('0');
        	return;
    	}

    
    	while (acc > 0){
        	c[i] = '0' + acc % 10;
        	acc /= 10;
        	i++;
    	}
    	c[i] = 0;

    	c2[i--] = 0;
    
    	while(i >= 0){
        	c2[i--] = c[j++];
    	}
    	monitor_write(c2);
}
